package edu.ecnu.yt.spring.di.spel;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.Log4jConfigurer;

@SuppressWarnings("deprecation")
@Configuration
@PropertySource("classpath:edu/ecnu/yt/spring/spel/myEnv.properties")
public class SpelConfig {
	
	@Bean
	public MethodInvokingFactoryBean methodInvokingFactoryBean() {
		MethodInvokingFactoryBean bean = new MethodInvokingFactoryBean();
		bean.setTargetClass(Log4jConfigurer.class);
		bean.setTargetMethod("initLogging");
		String[] arguments = {"classpath:config/log4j.properties"};
		bean.setArguments(arguments);
		return bean;
	}
	
	// 单引号需要用两个单引号转义
	@Bean
	public TestBean testBean1(@Value("#{'i''m a string'}") String msg) {
		return new TestBean(msg);
	}
	
	// 10的一次方
	@Bean
	public TestBean testBean2(@Value("#{10e0}") Integer msg) {
		return new TestBean(msg.toString());
	}
	
	@Bean
	public TestBean testBean3(@Value("#{true}") Boolean msg) {
		return new TestBean(msg.toString());
	}
	
	@Bean
	public TestBean testBean4(@Value("#{'${myEnv.name}'}") String msg) {
		return new TestBean(msg);
	}		
	
	@Bean
	public TestBean testBean4_1(@Value("#{systemProperties['java.version']}") String msg) {
		return new TestBean(msg);
	}	
	
	@Bean
	public TestBean testBean5(@Value("#{testBean1.msg}") String msg) {
		return new TestBean(msg);
	}
	
	@Bean
	public TestBean testBean6(@Value("#{testBean1.getMsg().toUpperCase()}") String msg) {
		return new TestBean(msg);
	}
	
	@Bean
	public TestBean testBean7(@Value("#{null}") String msg) {
		return new TestBean(msg);
	}
	
	// ?. 防止msg为null，如果为null返回null，如果没有?.将抛出异常
	@Bean
	public TestBean testBean8(@Value("#{testBean7.getMsg()?.toUpperCase()}") String msg) {
		return new TestBean(msg);
	}

	@Bean
	public TestBean testBean9(@Value("#{T(System).currentTimeMillis()}") Long msg) {
		return new TestBean(msg.toString());
	}
	
	// 静态调用，必须使用全名
	@Bean
	public TestBean testBean10(@Value("#{T(edu.ecnu.yt.spring.spel.TestBean).staticString}") String msg) {
		return new TestBean(msg);
	}
	
	// SpEL可以进行计算。该式表示从testBean2的msg（10的字符串）的平方（100）
	// 范围内取一随机数
	@Bean
	public TestBean testBean11(@Value("#{T(java.lang.Math).random() * "
			+ "T(java.lang.Integer).valueOf(testBean2.msg) ^ 2}") Double msg) {
		return new TestBean(msg.toString());
	}
	
	// 判断相等（也可以用==）
	@Bean
	public TestBean testBean12(@Value("#{T(java.lang.Boolean).valueOf(testBean3.msg) eq true}") Boolean msg) {		
		return new TestBean(msg.toString());
	}
	
	// 检查null并用default代替
	@Bean
	public TestBean testBean13(@Value("#{testBean7.getMsg() ?: 'defaultString'}") String msg) {		
		return new TestBean(msg);
	}
	
	// 正则表达式
	@Bean
	public TestBean testBean14(@Value("#{testBean13.getMsg() matches 'default.*'}") Boolean msg) {		
		return new TestBean(msg.toString());
	}
	
	/// 集合操作
	/// 如果想直接在SpEL中访问域(如直接访问name,age)，其可见性必须为public
	
	// 集合选择操作
	@Bean
	public TestBean testBean15(@Value("#{T(edu.ecnu.yt.spring.spel.TestBean).peoples[1].age}") Integer msg) {		
		return new TestBean(msg.toString());
	}
	
	// .?[]过滤选择子集操作，下式表示获取peoples集合中名称为a的人的集合，并将第二人的年龄给TestBean
	@Bean
	public TestBean testBean16(@Value("#{T(edu.ecnu.yt.spring.spel.TestBean).peoples.?[name eq 'a']}") People[] msg) {		
		return new TestBean(String.valueOf(msg[1].age));
	}
	
	// .^[]过滤选择第一个符合条件的元素操作(.$[]表示最后一个匹配项)，
	// 下式表示获取peoples集合中第一个名称为a的人的年龄
	@Bean
	public TestBean testBean17(@Value("#{T(edu.ecnu.yt.spring.spel.TestBean).peoples.^[name eq 'a'].age}") Integer msg) {		
		return new TestBean(msg.toString());
	}
	
	// .![]表示投影操作，下式表示将所有年龄为20的人的名称投影到一个新的String数组当中。
	@Bean
	public TestBean testBean18(@Value("#{T(edu.ecnu.yt.spring.spel.TestBean).peoples.?[age eq 20].![name]}") String[] msg) {		
		return new TestBean(Arrays.toString(msg));
	}
	
	
}
